Bag om supersøgeren Lucene

Lucene er en Java-baseret tekstsøgemaskine, som kan håndtere ganske store tekstmængder. Den indekserer i en rivende fart og indeholder masser af finurlig funktionalitet. I en tidligere artikel har vi set på, hvorledes Lucene kan anvendes i et konkret eksempel. Her ser vi på Java-koden bag eksemplet, og det er faktisk forbavsende simpelt.

50 millioner websider

Lucene er en Java-baseret maskine til indeksering og søgning i tekst. I forrige artikel om søgemaskinen viste vi, at selv på et gammelt hakkebræt af en computer klarer Lucene uden problemer fritekstsøgning gennem 500 megabyte data med øjeblikkelige svartider.

Lucene er ikke en database. Den holder ikke på data, men indekserer kun tekster, som må gemme sig andre steder. Det kan oplagt være i en database, men det kan også blot være flade filer på et drev.

Lucene er skrevet i Java, og er open source under samme licens som webserveren Apache, hvilket vil sige, at den kan anvendes også i kommercielle sammenhænge.

Hovedmanden bag Lucene er Doug Cutting, som har mange års erfaring indenfor teori og praksis angående søgemaskiner. Han står blandt andet bag websitet Excites søgning på indholdet på 50 millioner websider og en søgeteknologi, som er indbygget i Apples Macintosh-styresystem.

Første udgave af Lucene blev skrevet i 1998, og kildekoden blev udgivet under open source-licens i 2000.

Vi skal ikke gå i detaljer om virkemåden i Lucene, for det er en temmelig langhåret sag. Lucene benytter optimeringer af flere kendte metodikker i forbindelse med tekstsøgning, og det gør den ganske fint. En artikel i vort amerikanske søsterorgan JavaWorld beskriver virkemåden bag den effektive indeksering.

Men her ser vi nærmere på, hvorledes Lucene kan benyttes i egne applikationer.

Lucene er oplagt til brug i serversystemer, hvor de indekserede tekster kan være offentligt tilgængelige, eller blot fælles ressourcer, som for eksempel på et internt netværk eller intranet. Lucene kan downloades som Web-applikation (.war-fil), der kan benyttes med Tomcat eller andre Servlet-containere.

Men som i vores eksempel kan Lucene også anvendes til klient-systemer og helt almindelige Java-programmer.

Lucene indekserer kun, og berører ikke de indekserede tekster på anden vis. Derfor kan Lucene indeksere alle slags formater, bare teksten kan udtrækkes. Lucene kan altså også anvendes til formater som PDF og Word, bare man har en måde at udtrække teksten af formatet, og den slags filtre findes der mange af.

Teksten indekseres

Teksten indekseres
Lucene benyttes ved at downloade en jar-fil og tilføje den til classpath'en. Lucenes http://jakarta.apache.org/lucene/docs/api/" TARGET="_blank">API er veldokumenteret, og ganske nemt at følge. Der er mange måder at anvende Lucene på, og den vi skitserer her, berører kun en lille del af de mange muligheder.

Det objekt, som indekserer teksten og skriver de indekser, som Lucene benytter under søgningen, hedder IndexWriter. De genererede indekser kan gemmes på harddisken, i hukommelsen, i en database eller hvor man nu synes, at man vil gemme dem. Det nemmeste er blot at gemme dem på harddisken, så det gør vi her.

java.io.File indexes = new java.io.File("indexes");
writer = new IndexWriter(indexes, new SimpleAnalyzer(), true);

Før vi koder løs, opretter vi en mappe (directory) på harddisken, som vi døber "indexes". Så skaber vi en ny instans af IndexWriter, og constructoren giver vi tre argumenter. Første argument er mappen "indexes", som IndexWriter skal gemmes indekserne i. Det næste argument i constructoren er en instans af et Analyzer-objekt, og det skal forklares.

Lucene indekserer ikke alle ord ukritisk, men benytter en instans af et Analyzer-objekt til at filtrere eksempelvis ofte forekommende ord fra teksten, som ellers ville belaste indekserne unødigt og dermed give dårligere ydelse.

Derfor skal man benytte en Analyzer. Man kan skrive sin egen Analyzer, eller benytte en af de tre som medfølger i Lucene: SimpleAnalyzer, StandardAnalyzer og GermanAnalyzer. SimpleAnalyzer benyttes til engelsk, GermanAnalyzer til tysk, og ved hjælp af StandardAnalyzer og udvidelsen Snowball kan man benytte en lang række andre sprog, herunder dansk.

I vort eksempel fra forrige artikel var det encyklopædien Wikipedia, som er på engelsk, som vi ville indeksere, så derfor benytter vi en instans af SimpleAnalyzer.

Det sidste argument til IndexWriter er konstanten true, som angiver, at vi ønsker at skabe et nyt indeks i stedet for at anvende et allerede eksisterende.

Nu kan indekset fyldes med dokumenter. Det gøres ved hjælp af IndexWriters metode addDocument, og det, som skal lægges til, er et Lucene Document-objekt. Et dokument består af en række Field-instanser, som tilføjer tekst, der enten kan indekseres, eller blot gemmes i tilknytning til dokumentet. Det kan for eksempel være et filnavn, som senere kan identificere kilden.

Document document = new Document();

document.add(Field.UnIndexed("filename", filename));
document.add(Field.Text("title", title));
document.add(Field.Text("article", articleText));

writer.addDocument(document);

Som det ses, tilføjes Field-instanser ved hjælp af statiske metoder, som i

Field.UnIndexed("filename", filename)

Det første argument i metoden er feltnavnet, som blot er en streng ("filename"), der identificerer feltet. Dernæst er det så feltets indhold, som også er en streng. Denne metode genererer et felt, som ikke skal indekseres.

De tekster, som vi gerne vil indeksere, tilføjer vi dokumentet ved hjælp af metoden

Field.Text("title", title)

Ligesom før angiver første argument et feltnavn, mens næste argument, title, er teksten, som skal indekseres.

Til sidst tilføjes document-instansen til IndexWriter-instansen med linjen

writer.addDocument(document);

- og mere er der faktisk ikke i det - ud over at gennemløbe samtlige dokumenter på denne facon.

Som sagt er der masser af fleksibilitet i Lucenes indekseringsmuligheder, og i slutningen af denne artikel giver vi en række henvisninger til videre læsning.

Søgning

Søgning
Lucene indeholder en lang række søgemuligheder, inklusive sit eget søgesprog, mulighed for såkaldt fuzzy search, og mere til. Her kradser vi kun lige i lakken, men en af de rare ting ved Lucene er, at API'et er veldokumenteret og nemt at forstå.

Lad os forestille at vi vil gennemsøge artiklerne i vores encyklopædi-eksempel med søgestrengen "Napoleon". Det kunne se sådan ud:

String queryString = "Napoleon";
File indexes = new File(indexes");
Searcher searcher = new IndexSearcher(indexes.getAbsolutePath());
Query query =
  QueryParser.parse(queryString, "article", new SimpleAnalyzer());
Hits hits = searcher.search(query);
for (int i = 0; i < hits.length(); i++) {
  System.out.println(
  hits.doc(i).get("filename") + " score: " + hits.score(i));
}

Her gennemsøger vi vores tidligere skabte indeks med strengen "Napoleon". Det gøres med Lucene-objektet IndexSearcher, hvis constructor kaldes med stien til vores indeks som argument.

Dernæst skal vi bruge en instans af Lucenes Query-objekt. Query-instansen skabes ved hjælp af en statisk metode i objektet QueryParser:

Query query =
  QueryParser.parse(queryString, "article", new SimpleAnalyzer());

De tre argumenter er strengen vi leder efter, det felt i dokumenterne, hvor vi leder efter strengen (feltet "article"), og til sidst den Analyzer, som benyttedes ved indekseringen.

Søgningen udføres ved sætningen

Hits hits = searcher.search(query);

som populerer Hits-objektets instans med de dokumenter, som blev fundet ved søgningen.
Til sidst udskriver vi de fundne dokumenters filnavn, og hittets score, hvilket er dokumentets relevans.

Filnavnet gemte vi tidligere i et felt, som vi gav navnet "filename". Dette felt, og tilsvarende alle mulige andre felter som er tilknyttet det fundne dokument, kan hentes frem ved hjælp af linjen

hits.doc(i).get("filename")

Relevansen, hittets score, hentes med

hits.score(i)

Videre læsning
Den tidligere nævnte artikel fra JavaWorld giver en god introduktion til Lucene, og en anden udmærket online-artikel findes i tidsskriftet Java Developer's Journals arkiver.

Læses lige nu

    Formpipe Software A/S

    Senior Product Manager

    Københavnsområdet

    Netcompany A/S

    Linux Operations Engineer

    Københavnsområdet

    KMD A/S

    Teknisk Projektleder

    Nordjylland

    Forsvarsministeriets Materiel- og Indkøbsstyrelse

    Selvstændig IT-sagsbehandler til hardware, AV og TEMPEST i Cyberdivisionen i Hvidovre eller Karup

    Københavnsområdet

    Computerworld Events

    Vi samler hvert år mere end 6.000 deltagere på mere end 70 events for it-professionelle.

    Ekspertindsigt – Lyt til førende specialister og virksomheder, der deler viden om den nyeste teknologi og de bedste løsninger.
    Netværk – Mød beslutningstagere, kolleger og samarbejdspartnere på tværs af brancher.
    Praktisk viden – Få konkrete cases, værktøjer og inspiration, som du kan tage direkte med hjem i organisationen.
    Aktuelle tendenser – Bliv opdateret på de vigtigste dagsordener inden for cloud, sikkerhed, data, AI og digital forretning.

    It-løsninger | Nordhavn

    SAP Excellence Day 2026

    Få konkrete erfaringer med S/4HANA, automatisering og AI i praksis. Hør hvordan danske virksomheder realiserer gevinster og etablerer effektive SAP-løsninger. Vælg fysisk deltagelse hos SAP eller deltag digitalt.

    Infrastruktur | København

    Datacenterstrategi 2026

    Denne konference bidrager med viden om, hvordan du balancerer cloud, on-premise og hybrid infrastruktur med fokus på kontrol, compliance og forretning.

    Sikkerhed | Aarhus C

    Identity Festival 2026 - Aarhus

    Er du klar til en dag, der udfordrer din forståelse af, hvad Identity & Access Management kan gøre for din organisation? En dag fyldt med indsigt, inspiration og løsninger, der sætter kursen for, hvordan vi arbejder med IAM i de kommende år.

    Se alle vores events inden for it

    Navnenyt fra it-Danmark

    Idura har pr. 1. januar 2026 ansat Lars Mørch, 54 år,  som VP of Sales. Han skal især beskæftige sig med Iduras salgsorganisation, implementere en ny go-to-market-model og sikre udviklingen af virksomhedens identitetsplatform. Han kommer fra en stilling som Regional Vice President hos Avallone. Han er uddannet på CBS og har en BA i Organization & Innovation. Han har tidligere beskæftiget sig med internationalt SaaS-salg og forretningsudvikling fra både scale-ups og globale teknologivirksomheder. Nyt job

    Lars Mørch

    Idura

    Idura har pr. 1. januar 2026 ansat Joshua Pratt, 32 år,  som software engineer. Han skal især beskæftige sig med at bruge sin tekniske knowhow og erfaring i teamet for extensions og integrationer. Han kommer fra en stilling som Tech Director hos NoA Ignite Denmark. Han har tidligere beskæftiget sig med komplekse webprojekter, senest udviklingen af det nye website og e-commerce-platform for tivoli.dk. Nyt job

    Joshua Pratt

    Idura